%{
#include <stdio.h>
int yylex(void);
extern FILE *yyin;
int i = 0;


%}

%token T_PROGRAMA
%token T_FUNCAO
%token T_PROCEDIMENTO
%token T_INTEIRO
%token T_TEXTO
%token T_INICIO
%token T_FIM
%token T_IDENTIFICADOR
%token T_VAR
%token T_TIPO
%token T_PACKED
%token T_PARENTESES_A
%token T_PARENTESES_F
%token T_VIRGULA
%token T_INTEIRO_SEM_SINAL 
%token T_REAL_SEM_SINAL
%token T_CONSTANTE
%token T_PONTO
%token T_PONTO_VIRGULA
%token T_PARA
%token T_INCREMENTA
%token T_DECREMENTA
%token T_ENQUANTO
%token T_FACA
%token T_REPITA
%token T_ATE
%token T_DOIS_PONTOS
%token T_REGISTRO
%token T_DE
%token T_SE
%token T_ENTAO
%token T_SENAO
%token T_ATRIBUIR
%token T_ARQUIVO
%token T_COLCHETE_A
%token T_COLCHETE_F
%token T_MATRIZ
%token T_OP_ATRIBUICAO
%token T_OP_MAIOR
%token T_OP_MENOR
%token T_OP_MAIORIGUAL
%token T_OP_MENORIGUAL
%token T_OP_IGUAL
%token T_OP_DIFERENTE
%token T_OP_DIVISAO
%token T_OP_MULTIPLICACAO
%left T_OP_SUBTRACAO
%left T_OP_E
%left T_OP_OU
%left T_OP_NAO
%left T_OP_DIV
%left T_OP_MOD
%left T_OP_ADICAO

%start programa
%%
/* ###################################### INICIO ####################################### */

vazio:
	;
	
programa:
	cabecalho_programa T_PONTO_VIRGULA bloco_programa {
	$$ = tree_node_new("programa", PROGRAMA);
	tree_node_add_child($$, $1);
	tree_node_add_sibling($1, $3);
	root = $$;
	}
	;
	
cabecalho_programa:
	T_PROGRAMA nome_programa {
	$$ = tree_node_new("cabecalho_programa", CAB_PROGRAMA);
	tree_node_add_child($$, $2);
	symbol_add(&head, ((TreeNode*)$2)->name);
	}
	;
	
nome_programa:
	identificador {
		$$ = $1;
	}
	;

bloco_programa:
	bloco {
		$$ = $1;
	}
	;
	
bloco:
	parte_definicao_variaveis parte_instrucoes T_PONTO {
		tree_node_add_sibling($1, $2);
		$$ = $1;
	}
	;

identificador:
	T_IDENTIFICADOR {
		$$ = tree_node_new($1, IDENTIFICADOR);
		//symbol_add(&head, $1);
	}
	;


/* ###################################### CONSTANTE ####################################### */	


numero_sem_sinal:
	T_INTEIRO_SEM_SINAL
	{
		$$ = tree_node_new($1, CONST_INTEIRA);
		symbol_addFromNode(&head, $$, tree_node_new("inteiro", TIPO));
	}
	;

/* ######################################## TIPO ######################################### */	

/*melinho inicio adicionado*/

tipo:
	variavel {
		//$$ = tree_node_new($1, TIPO);
		//tree_node_add_child($$, $1);
		$$ = $1;
	}
	
	;

/*melinho fim adicionado*/

/* ###################################### VARIAVEL ####################################### */

/*melinho inicio adicionado*/

parte_definicao_variaveis:
	T_VAR declaracao_de_variavel repeticao_declaracao_de_variavel 
	{
		$$ = tree_node_new("parte_definicao_variaveis", DECLARACAO_VARIAVEL);
		tree_node_add_child($$, $2);
		tree_node_add_sibling($2, $3);
	}
	| vazio {$$ = NULL;}
	;
	
declaracao_de_variavel:
	variavel repeticao_variavel T_DOIS_PONTOS tipo T_PONTO_VIRGULA 
	{
		$$ = tree_node_new("declaracao_de_variavel", TIPO);
		tree_node_add_child($$, $1);
		tree_node_add_sibling($1, $2);
		symbol_addFromNode(&head, $1, $4);
	}
	;

repeticao_declaracao_de_variavel:
	declaracao_de_variavel repeticao_declaracao_de_variavel
	{
		tree_node_add_sibling($1, $2);
		$$ = $1;
	}
	| vazio {$$ = NULL;}
	;

repeticao_variavel:
	T_VIRGULA variavel repeticao_variavel
	{
		tree_node_add_sibling($2, $3);
		$$ = $2;
	}
	| vazio {$$ = NULL;}
	;

/*melinho fim adicionado*/

variavel:
	identificador {
		$$ = $1;
	}
	;

	
/* ###################################### INSTRUCAO ####################################### */


parte_instrucoes:
	instrucao_composta {
		$$ = $1;
	}
	;

instrucao_composta:
	T_INICIO instrucao_lista T_FIM {
		$$ = $2;
	}
	;
	
instrucao_lista:
	instrucao repeticao_instrucao {
		$$ = tree_node_new("instrucao_lista", INSTRUCAO_LISTA);
		tree_node_add_child($$, $1);
		tree_node_add_sibling($1, $2);
	}
//	| vazio {$$ = NULL;}
	;
	
repeticao_instrucao:
	T_PONTO_VIRGULA instrucao repeticao_instrucao {
		tree_node_add_sibling($2, $3);
		$$ = $2;
	}
	| vazio {$$ = NULL;}
	;
	
instrucao:
	instrucao_simples {
		$$ = $1;
	}
	| vazio {$$ = NULL;}
	;
	
instrucao_simples:
	instrucao_de_atribuicao {
		$$ = $1;
	}
	;

instrucao_de_atribuicao:
	variavel T_OP_ATRIBUICAO expressao {
		$$ = tree_node_new("instrucao_de_atribuicao", INSTRUCAO_ATRIBUICAO);
		tree_node_add_child($$, $1);
		tree_node_add_sibling($1, $3);
	}
	;

expressao:
	expressao_simples {
		$$ = $1;
	}
	;

expressao_simples:
	termo {
		$$ = $1;
	}
	//	| T_OP_SUBTRACAO termo {
//		$$ = tree_node_new("expressao_simples", REGRA);
//		TreeNode *nodeSinal = tree_node_new("-", REGRA);
//		tree_node_add_child($$,nodeSinal);
//		tree_node_add_sibling(nodeSinal, $2);
//	}
//	| T_OP_ADICAO termo {
//		$$ = tree_node_new("expressao_simples", REGRA);
//		TreeNode *nodeSinal = tree_node_new("+", REGRA);
//		tree_node_add_child($$,nodeSinal);
//		tree_node_add_sibling(nodeSinal, $2);
//	}
	| operacao termo { //melinho adicionado
		$$ = tree_node_new("operacao", REGRA);
		tree_node_add_child($$,$1);
		tree_node_add_sibling($1, $2);
	}
	| expressao_simples operador_adicional termo {
		$$ = tree_node_new("expressao_bin", EXP_SIMPLES);
		tree_node_add_child($$, $1);
		tree_node_add_sibling($1, $2);
		tree_node_add_sibling($1, $3);
	}
	;

//melinho inicio adicionado

operacao:
	T_OP_SUBTRACAO  {
		$$ = tree_node_new("operacao", REGRA);
		tree_node_add_child($$,tree_node_new("-", IDENTIFICADOR));
	}
	| T_OP_ADICAO	{
		$$ = tree_node_new("operacao", REGRA);
		tree_node_add_child($$,tree_node_new("+", IDENTIFICADOR));
	}
	;

//melinho fim adicionado

termo:
	fator {
		$$ = $1;
	}
	/*	
	| termo operador_multiplicador fator {
		$$ = tree_node_new("termo", REGRA);
		tree_node_add_child($$, $1);
		tree_node_add_sibling($1, $2);
		tree_node_add_sibling($1, $3);
	}
	*/
	;
	
/*
operador_multiplicador:
	T_OP_DIVISAO	{$$ = tree_node_new($1, OPERADOR);}
	| T_OP_E	{$$ = tree_node_new($1, OPERADOR);}
	| T_OP_MOD	{$$ = tree_node_new($1, OPERADOR);}
	| T_OP_DIV 	{$$ = tree_node_new($1, OPERADOR);}
	| T_OP_MULTIPLICACAO	{$$ = tree_node_new($1, OPERADOR);}
	;
*/

fator:
	variavel {
		$$ = $1;
	}
	| T_PARENTESES_A expressao T_PARENTESES_F {
		$$ = $2;
	}
	| T_OP_NAO fator {
		$$ = $2;
	}
	| numero_sem_sinal {
		$$ = $1;
	}
	;

operador_adicional:
	T_OP_ADICAO	{$$ = tree_node_new($1, OPERADOR);}
	| T_OP_SUBTRACAO {$$ = tree_node_new($1, OPERADOR);}
	| T_OP_OU	{$$ = tree_node_new($1, OPERADOR);}
	;


/* ###################################### FIM #################################### */

%%

int yyerror(char *s) {
        printf("\nyyerror %s\n", s);
}

int mainParser() {
    yyparse();
}
